#include "stdafx.h"
#include "hzWindow.h"
#include "inlineFunction.h"

using namespace hz;
using namespace core;



window::window(void) 
: _hWnd(NULL) {	
}
window::~window(void) {
}


const HWND& window::GetHWND(void) const {
	return _hWnd;
}

const window::attribute& window::GetAttribute(void) const {
	return _Attribute;
}

void window::UpdateWindowPos(void) {
	RECT rt;

	GetWindowRect(_hWnd, &rt);
	_Attribute.WindowPos.x = (float)rt.left;
	_Attribute.WindowPos.y = (float)rt.top;	
}

void window::UpdateWindowClientSize(void) {
	RECT rt;

	GetClientRect(_hWnd, &rt);
	_Attribute.WindowClientSize.x = (float)rt.right;
	_Attribute.WindowClientSize.y = (float)rt.bottom;	
}

bool window::Init(HINSTANCE hInst, wstring windowName, wstring title, 
				  const window* parents, int x, int y, int width, int height, bool fullscreen,
				  DWORD style, UINT wndStyle, int menuResource, 
				  HICON icon, HICON iconSm, HCURSOR cursor,	HBRUSH background) {		
	_Attribute.Type			= WINDOW;
	_Attribute.FullScreen	= fullscreen;
	_Attribute.Menu			= (menuResource != NULL)	?	true : false;
	_Attribute._TitleBarName = title;
	_Attribute.WindowName	= windowName;	
	_Attribute.Minimized	= false;
	_Attribute.Focus		= true;

					  
	HRESULT hr;
	
	WNDCLASSEX wcex;	
	wcex.cbSize			= sizeof(WNDCLASSEX);
	wcex.style			= wndStyle;
	wcex.lpfnWndProc	= staticWinProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInst;
	wcex.hIcon			= icon;
	wcex.hIconSm		= iconSm;
	wcex.hCursor		= cursor;
	wcex.hbrBackground	= background;	
	wcex.lpszClassName	= windowName.c_str();	
	if(menuResource != NULL)
		wcex.lpszMenuName	= MAKEINTRESOURCE(menuResource);
	else
		wcex.lpszMenuName	= NULL;
			
	hr = RegisterClassEx(&wcex);
	if(FAILED(hr))
		return false;

	_hWnd = CreateWindow(windowName.c_str(), title.c_str(), style,
		CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 
		((parents)? parents->GetHWND() : NULL), NULL, 
		hInst, 
		NULL);
	if(_hWnd == NULL)
		return false;	

	hr = ShowWindow(_hWnd, SW_SHOW);	
	hr = UpdateWindow(_hWnd);

	ChangeWindow(x, y, width, height);	

	

	_WindowStyle = style;	
	_hMenu = GetMenu(_hWnd);	

	SetWindowLongPtr(_hWnd, GWLP_USERDATA, (LONG)this);
				  
	return true;
}

bool window::Init(const process& windowProcess, DWORD dialogResourceID, const window* parents) {
	HRESULT hr;

	_hWnd = CreateDialog(windowProcess.GetAttribute().hInstance,
				 MAKEINTRESOURCE(dialogResourceID),
				 (parents? parents->GetHWND() : NULL), 
				 (DLGPROC)staticDialogProc);	 

	hr = SetWindowLongPtr(_hWnd, GWLP_USERDATA, (LONG)this);

	hr = ShowWindow(_hWnd, SW_SHOW);


	wchar_t TempString[256];	
	_Attribute.Type			= DIALOG;
	_Attribute.FullScreen	= false;
	_Attribute.Menu			= false;
	_Attribute.WindowName.clear();
	_Attribute.Minimized	= false;
	_Attribute.Focus		= true;
	GetWindowText(_hWnd, TempString, 256);
	_Attribute._TitleBarName = TempString;
	UpdateWindowPos();
	UpdateWindowClientSize();

	return true;
}

bool window::ChangeWindow(int x, int y, int width, int height) {
	if(_hWnd == NULL)
		return false;

	HRESULT hr;
	
	if(x == CW_USEDEFAULT) {	
		RECT rWindowPosition;
		GetWindowRect(_hWnd, &rWindowPosition);
		x = rWindowPosition.left;
		y = rWindowPosition.top;
	}
	if(width == CW_USEDEFAULT) {
		RECT rWindowClientSize;
		GetClientRect(_hWnd, &rWindowClientSize);
		width = rWindowClientSize.right;
		height = rWindowClientSize.bottom;		
	}
	
	RECT rWindow = {x, y, width, height};
         
     // Get new real window size 
	DWORD dwStyle = GetWindowLong(_hWnd, GWL_STYLE);
	AdjustWindowRect(&rWindow, dwStyle, _Attribute.Menu);
    rWindow.right  -= rWindow.left - x;
    rWindow.bottom -= rWindow.top - y;
     
	
	MoveWindow(_hWnd, x, y, rWindow.right, rWindow.bottom, true);	
	UpdateWindowPos();
	UpdateWindowClientSize();	

	return true;
}

bool window::ChangeWindow(DWORD style) {
	SetWindowLong(_hWnd, GWL_STYLE, style);
	return true;
}

bool window::ChangeWindow(void) {	
	if(_Attribute.FullScreen) {	
		SetMenu(_hWnd, _hMenu);
		SetWindowLong(_hWnd, GWL_STYLE, this->_WindowStyle);
		
		MoveWindow(_hWnd, _WindowRect.left, _WindowRect.top, 
						  _WindowRect.right - _WindowRect.left, 
						  _WindowRect.bottom - _WindowRect.top, true);		

		
	}
	else {
		_WindowStyle = GetWindowLong(_hWnd, GWL_STYLE);
		_hMenu = GetMenu(_hWnd);
		GetWindowRect(_hWnd, &_WindowRect);

		SetWindowLong(_hWnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
		SetMenu(_hWnd, NULL);

		HDC hdc = GetDC(_hWnd);
		MoveWindow(_hWnd, 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES), true);	
	}

	_Attribute.FullScreen = !_Attribute.FullScreen;
	(GetMenu(_hWnd) != NULL) ? _Attribute.Menu = true : _Attribute.Menu = false; 
	return true;
}


bool CALLBACK window::CustomProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
	return false;
}


LRESULT CALLBACK window::staticWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{	
	window *ClassAccess = (window*)GetWindowLongPtr(hWnd, GWLP_USERDATA);

	if(ClassAccess == NULL) 
		return DefWindowProc(hWnd, message, wParam, lParam);


#ifdef _DEBUG
	// develop support funtion
	if(message ==  WM_KEYDOWN)
		if( (GetKeyState(VK_CONTROL) & 0xFF00) && (GetKeyState('W') & 0xFF00) ) {
			const HWND &hWnd = ClassAccess->GetHWND();
			wchar_t infoText[256];
			RECT rt;

			if(GetKeyState(VK_F1) & 0xFF00) {	// View Client Size 
				GetClientRect(hWnd, &rt);
				wsprintf(infoText, _T("width : %d         height : %d"), rt.right, rt.bottom);
				MessageBox(hWnd, infoText, _T("Client Size"), MB_OK);			
			}

			if(GetKeyState(VK_F2) & 0xFF00) {	// View Window Rect
				GetWindowRect(hWnd, &rt);
				wsprintf(infoText, _T(" left : %d / top : %d / right : %d / bottom : %d"), 
										rt.left, rt.top, rt.right, rt.bottom);
				MessageBox(hWnd, infoText, _T("Windor Rect"), MB_OK);			
			}

			if(GetKeyState(VK_F3) & 0xFF00) {	// attribute's pos
				wsprintf(infoText, _T("x : %d         y : %d"), 
									  (int)ClassAccess->GetAttribute().WindowPos.x,
									  (int)ClassAccess->GetAttribute().WindowPos.y);
				MessageBox(hWnd, infoText, _T("attribute's pos"), MB_OK);		
			}

			if(GetKeyState(VK_F4) & 0xFF00) {	// attribute's Size
				wsprintf(infoText, _T("x : %d         y : %d"), 
									(int)ClassAccess->GetAttribute().WindowClientSize.x,
									(int)ClassAccess->GetAttribute().WindowClientSize.y);
				MessageBox(hWnd, infoText, _T("attribute's client size"), MB_OK);		
			}

			if(GetKeyState(VK_F5) & 0xFF00) {	// attribute's boolean
				wsprintf(infoText, _T(" Fullscreen : %s / Menu : %s / Minimized : %s / Focus : %s "),
									BoolToText(ClassAccess->GetAttribute().FullScreen),
									BoolToText(ClassAccess->GetAttribute().Menu),
									BoolToText(ClassAccess->GetAttribute().Minimized),
									BoolToText(ClassAccess->GetAttribute().Focus) );
				MessageBox(hWnd, infoText, _T("attribute's client size"), MB_OK);		
			}
		}
#endif

	if(message ==  WM_SIZE) {
		(wParam == SIZE_MINIMIZED) ? ClassAccess->_Attribute.Minimized = true 
									:ClassAccess->_Attribute.Minimized = false;
		
		ClassAccess->UpdateWindowClientSize();
	}
	if(message ==  WM_MOVE) 
		ClassAccess->UpdateWindowPos();
	if(message == WM_ACTIVATEAPP) 
		(wParam == TRUE) ? ClassAccess->_Attribute.Focus = true 
						  :ClassAccess->_Attribute.Focus = false;
	


	if(ClassAccess->CustomProc(hWnd, message, wParam, lParam))
		return 0;
	else
		return DefWindowProc(hWnd, message, wParam, lParam);
}

LRESULT CALLBACK window::staticDialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{	
	window *ClassAccess = (window*)GetWindowLongPtr(hWnd, GWLP_USERDATA);

	if(ClassAccess == NULL) 
		return DefWindowProc(hWnd, message, wParam, lParam);
	
	if(ClassAccess->CustomProc(hWnd, message, wParam, lParam))
		return TRUE;
	else
		return FALSE;	
}

